-
Notifications
You must be signed in to change notification settings - Fork 13.6k
lint ImproperCTypes: overhaul (take 2 of "better handling of indirections") #134697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
( |
ah, and before I forget: a small part of the new test file is commented out because it hits ICE #134587, but there should be more than decent coverage anyway |
unfortunately the lint needs to be gutted and rewritten. |
Also while I was possibly having a mild case of get-there-itis and thus mostly tried to just make sure things were coherent, I would prefer all new code for the lint be in |
The version cut happened so there will be less time pressure now. |
I have a first version for you probably have things to say about its architecture, even if the whole thing still have a bunch of TODO comments
If you want to take a look in this state, should I just commit it here? (possibly put the PR in draft mode while I'm at it?) |
☔ The latest upstream changes (presumably #135525) made this pull request unmergeable. Please resolve the merge conflicts. |
5764b36
to
6c19cff
Compare
aaaand I think I have something that's "first draft" material! (should I put this pull in the "draft" state?) here's a list of some of my remaining questions and concerns:
|
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #135921) made this pull request unmergeable. Please resolve the merge conflicts. |
6c19cff
to
13720e7
Compare
This comment has been minimized.
This comment has been minimized.
hmm. |
Yes, it's a good marker for "I don't want this merged yet, even if it looks done". |
It probably is.
Yes, but in particular, not to just repartition them between: I think breaking them into as many conceptually-smaller lints as possible is good, as long as each one is a distinct idea (no splitting just for the sake of splitting!).
I'm not sure what you mean?
We must allow Rust code to declare a pointer in a C signature to be
Yes, probably. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some initial nits on a first pass
// but for some reason one can just go and write function *pointers* like that: | ||
// `type Foo = extern "C" fn(::std::ffi::CStr);` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Because unsized function parameters are something we may want to support.
- The code may not be well-formed: as you may have noticed at some point, you get warnings even if you get errors (usually), and this is because we lint even on "bad" code. This is because rustc didn't use to, once upon a time, and it was a bad debugging experience.
alright, sorry for taking a while! I'm currently planning what changes I'll do in terms of splitting the lint(s)
well, this is more or less answered in what I said before that, but my question was about how to deal with "switching" from checking arguments for, say, a function definition, to checking the arguments of a FnPtr argument?
I... maybe? I can't for the life of me find the link to that again but I think I saw a discussion about that and type covariance/contravariance, Though you'll definitely know more than me on all the moving parts. As for the rest of your advice, I already took all this in! |
visitation steps [does not pass tests]
- removed special-case logic for a few cases (including the unit type, which is now only checked for in one place) - moved a lot of type-checking code in their dedicated visit_* methods - reworked FfiResult type to handle multiple diagnostics per type (currently imperfect due to type caching) - reworked the messages around CStr and CString
…ed from non-rust code
- now the lint scans repr(C) struct/enum/union definitions - it now also scans method declarations in traits - many other changes in the underlying logic - some extra tests
- also fix a couple of thorny typos in/around types.rs::is_outer_optionlike_around_ty() and subsequently fix library and tests
- do not check ADT definitions themselves, it turns out `repr(C)` is not a strong enough signal to determine if something is designed for FFIs - however, start checking static variables with `#[no_mangle]` or `#[export_name=_]`, even if that's not a perfect signal due to the lack of specified ABI - some changes to the LLVM codegen so it can be seen as FFI-safe
for now, let's fully remove this lint. it might be reintroduced later as a way to make the lints ignore the inside of some ADT definitions
- make clippy happy about the changes in rust_codegen_llvm - split a test stderr into 32bit and 64bit - fix some documentation
754eaee
to
f19f4da
Compare
This PR modifies
cc @tgross35 |
This comment has been minimized.
This comment has been minimized.
re: not making changes in compiler-builtins: |
For future reference, it's fine for small changes like this to go through rust-lang/rust. I just was curious about the results since i128 got removed from improper_ctypes a while ago, and wanted a CI run in that repo. |
f19f4da
to
c414d41
Compare
This comment has been minimized.
This comment has been minimized.
it would be correct to lint on those, but this is deemed too steep a change for now, especially for projects that turn all warnings into errors
- relaxed the uninhabited types allowed on function return
c414d41
to
0d80e12
Compare
☔ The latest upstream changes (presumably #145210) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A meta question that may be somewhere in this discussion: could the current names be kept around as groups? E.g. make improper_ctypes_definitions
a group for improper_c_fn_definitions
and improper_c_callbacks
, to help avoid the ecosystem churn.
It would be very helpful if you could update the PR message to summarize the user-visible changes from this, mentioning the specific lint names and maybe tiny examples.
Also, does this happen to fix #132699? I think it might but didn't see a test or Fixes:
tag.
question, @workingjubilee: Do I rebase this branch now? I have no idea if you (or someone else) is in the middle of a review, and I would rather avoid changing the code while you're looking at it. But at the same time, you might be waiting for me to rebase to do another round of review so... yeah.
Yeah that triagebot warning is far too noisy. I don't really think there's much need to rebase unless there are conflicts (not really tests) or if something about the code you're working on has changed.
However, you may want to re-split your commits / squash some so they each only contains active code. I started doing a breeze through review and since this is huge started to do it by commit, only to find out that a lot of the code from the first commits is completely gone 🙃
pub(crate) fn LLVMRustBuildMinNum<'a>( | ||
B: &Builder<'a>, | ||
LHS: &'a Value, | ||
RHS: &'a Value, | ||
LHS: &'a Value, | ||
) -> &'a Value; | ||
pub(crate) fn LLVMRustBuildMaxNum<'a>( | ||
B: &Builder<'a>, | ||
LHS: &'a Value, | ||
RHS: &'a Value, | ||
LHS: &'a Value, | ||
) -> &'a Value; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's going on with this change (two args named LHS)?
#[allow(improper_ctypes)] | ||
unsafe extern "C" { | ||
unsafe extern "Rust" { | ||
#[rustc_std_internal_symbol] | ||
fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing the ABI here is orthogonal to the lint change, could you drop this part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AIUI, you don't need to do changes to this file by hand since they get autogenerated at sync time
extern "C" { | ||
fn meh(blah: Foo); | ||
//~^ WARN `extern` block uses type | ||
// ^ FIXME: the error isn't seen here but at least it's reported elsewhere |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Always using something like FIXME(ctypes)
makes it much easier to find related changes among the thousands of FIXMEs
//@ aux-build: outer_crate_types.rs | ||
//@ compile-flags:--extern outer_crate_types | ||
extern crate outer_crate_types as outer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extern_crate_types
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're trying to get away from tests named by numbers, so make sure any new files get a descriptive name (f not also a one line description in the file). An // Issue: https://github.com/rust-lang/rust/issues/94223
comment is the loose convention for keeping things linked.
#[repr(C)] | ||
#[derive(Clone,Copy)] | ||
struct TemplateStruct<T> where T: std::ops::Add+Copy { | ||
one: T, | ||
two: T, | ||
} | ||
impl<T: std::ops::Add+Copy> TemplateStruct<T> { | ||
type Out = <T as std::ops::Add>::Output; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: run rustfmt on this file, looks like indentation is mixed
#[non_exhaustive] | ||
#[repr(C)] | ||
pub struct UnitStruct; | ||
//#[non_exhaustive] | ||
//#[repr(C)] | ||
//pub struct UnitStruct; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this commented?
This adds more visitors so it should get a perf run at some point (requires a conflict-free merge to master) |
This PR started as a try to re-add the changes of #131669 (reverted in #134064 after one (1) nightly)
It has since evolved in an overhaul of the ImproperCTypes lints, splitting the two lints into four:
extern "ABI"
blocksextern "ABI"
functions#[no_mangle]
/1[export_name=_]
static variablesextern "ABI"
callbacks (ty::FnPtr
arguments/return types/ADT fields)It also allows for "detailed" lint messages, with successive notes that amount to "this is unsafe because of that, which is unsafe because of that, which is unsafe for this reason", and possible help messages at every step.
Hopefully the overall architecture of the lint is something less special-case-y, with better-separated abstractions.
the comment containing the most recent summary of the decisions and considerations is #134697 (comment)
oh, also, since this was already fixing it for the wrong reasons, I decided to add something that fixes it for the right ones:
Fixes #130310
(leaving this in because it was in the original version of this description:)
r? workingjubilee (because you reviewed the first attempt)